<?php

// vim: expandtab shiftwidth=2 softtabstop=2 tabstop=2

/**
 * Group of functions to operations on strings
 *
 * PHP version 5
 *
 * @category  Namespaces
 * @package   mPack
 * @author    Marcin Sztolcman <marcin /at/ urzenia /dot/ net>
 * @copyright 2006 Marcin Sztolcman
 * @license   GPL v.2
 * @version   SVN: $Id: ns_strings.php 29 2008-01-20 23:15:20Z urzenia $
 * @link      http://m-pack.googlecode.com
 */

/**
 * Group of functions to operations on strings
 *
 * @category  Namespaces
 * @package   mPack
 * @author    Marcin Sztolcman <marcin /at/ urzenia /dot/ net>
 * @copyright 2006 Marcin Sztolcman
 * @license   GPL v.2
 * @version   SVN: $Id: ns_strings.php 29 2008-01-20 23:15:20Z urzenia $
 * @link      http://m-pack.googlecode.com
 */
abstract class Strings {
  /**
   * Parse string using class {@link Parser}
   *
   * @param string $s string to parse
   * @param string $encoding encoding input data
   * @param boolean $wellFormed does passed string is well formed XML?
   *
   * @return mixed {@link Parser::parse()}
   * @throws InvalidArgumentException if class Parser not found
   * @access public
   * @static
   */
  public static function parse($s, $encoding='UTF-8', $wellFormed=false, $parserClass='Parser')
  {
    if (!class_exists($parserClass)) {
      throw new InvalidArgumentException(sprintf('Class "%s" not found.', $parserClass), 140);
    }
    if (!in_array('parse', get_class_methods($parserClass))) {
      throw new InvalidArgumentException(sprintf('Method "parse" in class "%s" not found.', $parserClass), XXX);
    }
    $parser = new $parserClass;
    return $parser->parse($s, $encoding, $wellFormed);
  }

  /**
   * Converts html < br /> tag to new line char
   *
   * @param string $s
   * @param string $nl new line characters
   *
   * @access public
   * @static
   * @staticvar array $br html < br /> tags used when seeking for them
   */
  public static function br2nl($s, $nl="\n")
  {
    static $br = array('<br />', '<br>', '<br/>');
    return str_replace($br, $nl, $s);
  }

  /**
   * Converts special chars to html entities
   *
   * @param string $s
   * @param boolean $striprn replace new line chars with space?
   *
   * @access public
   * @static
   * @staticvar array $p special chars to replace
   * @staticvar array $r html entities
   */
  public static function entities($s, $striprn=false)
  {
    static $p = array(
      '<' => '&lt;',
      '>' => '&gt;',
      '"' => '&quot;',
      "'" => '&#39;'
    );
    $ret = strtr($s, $p);

    if ($striprn) {
      $ret = str_replace(array("\r\n", "\r", "\n"), ' ', $ret);
    }

    return $ret;
  }

  /**
   * Insert links into html <a /> tag
   *
   * @param  string 4s
   *
   * @access public
   * @static
   * @staticvar array $p pattern used in {@link http://php.net/preg_replace preg_replace()}
   * @staticvar array $r replacement used in {@link http://php.net/preg_replace preg_replace()}
   */
  public static function htmlizelinks($s)
  {
    static $p = array(
      '#(^|[\n ])([\w]+?://[^ "\n\r\t<]*)#i',
      '#(^|[\n ])((www|ftp)\.[^ "\t\n\r<]*)#i',
      '#(^|[\n ])([a-z0-9&\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i'
    );
    static $r = array(
      '\\1<a href="\\2">\\2</a>',
      '\\1<a href="http://\\2">\\2</a>',
      '\\1<a href="mailto:\\2@\\3">\\2@\\3</a>'
    );
	    return preg_replace($p, $r, $s);
  }

  /**
   * Checks for $string starts with $prefix
   *
   * Case sensitive.
   *
   * @param string $string
   * @param string $prefix
   *
   * @access public
   * @static
   */
  public static function startswith($string, $prefix)
  {
    return (substr($string, 0, strlen($prefix)) == $prefix);
  }

  /**
   * Checks for $string ends with $prefix
   *
   * Case sensitive.
   *
   * @param string $string
   * @param string $postfix
   *
   * @access public
   * @static
   */
  public static function endswith($string, $postfix)
  {
    return (substr($string, -strlen($postfix)) == $postfix);
  }

  /**
   * Checks for $string starts with $prefix
   *
   * Case insensitive.
   *
   * @param string $string
   * @param string $prefix
   *
   * @access public
   * @static
   */
  public static function istartswith($string, $prefix)
  {
    return (strtolower(substr($string, 0, strlen($prefix))) == strtolower($prefix));
  }

  /**
   * Checks for $string ends with $prefix
   *
   * Case insensitive.
   *
   * @param string $string
   * @param string $postfix
   *
   * @access public
   * @static
   */
  public static function iendswith($string, $postfix)
  {
    return (strtolower(substr($string, -strlen($postfix))) == strtolower($postfix));
  }

  /**
   * Print string in column at $width chars wide, and alig text to left.
   *
   * @param string  $string
   * @param integer $width width of columnt
   * @param string  $type  string used to use when padding string
   * @param boolean $entit if true, use $type as html entity and treat it as single char
   *
   * @access public
   * @static
   */
  public static function left($string, $width, $type=' ', $entit=true)
  {
    if ($entit) {
      $len = strlen($string);
      if ($width > $len) {
        $width = ($width - $len)*strlen($type) + $len;
      }
    }
    return str_pad($string, $width, $type, STR_PAD_RIGHT);
  }

  /**
   * Print string in column at $width chars wide, and alig text to right.
   *
   * @param string  $string
   * @param integer $width width of columnt
   * @param string  $type  string used to use when padding string
   * @param boolean $entit if true, use $type as html entity and treat it as single char
   *
   * @access public
   * @static
   */
  public static function right($string, $width, $type=' ', $entit=true)
  {
    if ($entit) {
      $len = strlen($string);
      if ($width > $len) {
        $width = ($width - $len)*strlen($type) + $len;
      }
    }
    return str_pad($string, $width, $type, STR_PAD_LEFT);
  }

  /**
   * Return string in column at $width chars wide, and align text to center.
   *
   * @param string  $string
   * @param integer $width width of columnt
   * @param string  $type  string used to use when padding string
   * @param boolean $entit if true, use $type as html entity and treat it as single char
   *
   * @access public
   * @static
   */
  public static function center($string, $width, $type=' ', $entit=true)
  {
    if (!$entit) {
      return str_pad($string, $width, $type, STR_PAD_BOTH);
    }

    $len   = strlen($string);

    $left  = ceil(($width-$len)/2);
    $right = $width - $len - $left;

    $left  = implode('', array_pad(array(), $left,  $type));
    $right = implode('', array_pad(array(), $right, $type));

    return $left . $string . $right;
  }

  /**
   * Smart cut string with BBCode tags to $len length.
   *
   * @param string  $string
   * @param integer $length max length of cutted text
   *
   * @access public
   * @static
   */
  public static function cutwithbbcode($string, $length) {
    static $tags = array(
      'single'  => array('br', 'hr'),
      'double1' => array('quote','b', 'i', 'u', 'color', 'center',),
      'double2' => array('img','url',)
    );
    $pat = sprintf('!(\[/?(?:%s)(?:\s*=\s*.*?]*)?\])!i', Arrays::multijoin('|', $tags));

    $splitted = preg_split($pat, $string, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
    $count    = 0;
    $stack    = array();
    $new      = array();
    $append   = false;
    foreach ($splitted as $part) {

      $tag = 0;
      if (preg_match('!^\[(img|quote|url|b|i|u|color|center)(\s*=\s*.*?)?\]$!i', $part, $match)) { //tag rozpoczynający
        $tag = array_slice($match, 1);
        $append = (in_array($tag[0], $tags['double2']) && count($tag) == 1);
        array_push($stack, $tag[0]);
      }
      else if (preg_match('!^\[/(img|quote|url|b|i|u|color|center)\]$!i', $part)) { //tag kończący
        array_pop($stack);
        $append = false;
      }
      else if (preg_match('!^\[(br|hr)\]$!i', $part)) { //tag pojedynczy
        // pass
      }
      else {
        $l = strlen($part);
        if (($count+$l) >= $length) {
          if ($append) {
            array_splice($new, -1, 1, substr(end($new), 0, -1) . '=' . $part . ']');
          }

          $new[] = substr($part, 0, -($count+$l-$length));
          while ($el = array_pop($stack)) {
            $new[] = sprintf('[/%s]', $el);
          }
          break;
        }
        $count += $l;
        $append = false;
      }

      $new[] = $part;

    }

    return join('', $new);
  }

}

?>
